/*
 * Szene.cpp
 *
 *  Created on: Feb 15, 2011
 *      Author: alki
 */

#include "Szene.h"
#include <stdlib.h>
#include <iostream>

#include "loader/Loader.h"

Szene::Szene(unsigned int width,unsigned int height,unsigned int jitter,unsigned int diffus,unsigned int maxtiefe) {
	this->m_objekte.clear();
	this->m_width = width;
	this->m_height = height;
	this->m_jitter = jitter;
	this->m_diffus = diffus;
	this->m_maxtiefe = maxtiefe;
	this->m_tree = NULL;
}

Szene::~Szene() {
	this->m_objekte.clear();
	if(this->m_tree!=NULL) {
		delete this->m_tree;
		this->m_tree = NULL;
	}
}

void Szene::LoadFile(string filename) {
	Loader loader;
	loader.LoadFile(filename,this->m_objekte,this->m_matman);

	for(unsigned int i=0;i<this->m_objekte.size();i++) {
		this->m_objekte[i].CalcPosition();
		this->m_objekte[i].CalcRadius();
		this->m_objekte[i].CalcVNormals();
		this->m_objekte[i].AddMaterialManager(&this->m_matman);
		this->m_objekte[i].index=i;
	}

	this->m_tree = new KDTree();
	for(unsigned int i=0;i<this->m_objekte.size();i++) {
		this->m_tree->insert(&(this->m_objekte[i]));
	}
	this->m_tree->resize();
	this->m_tree->split(1);
//	this->m_tree->out(3);
}

FARBE Szene::CalcRay(unsigned int x,unsigned int y) const {
	FARBE color;

	Gerade ray;
	ray.setPos(this->m_pos);

	for(unsigned int filter=0;filter<this->m_jitter;filter++) {
		ray.setDir(this->Pixel2Dir(x,y));
		ray.CalcHelpers();
		color=color+this->CalcRay(ray);
	}
	return color/this->m_jitter;
}

Vektor Szene::Pixel2Dir(unsigned int x,unsigned int y) const {
	float X=x;
	float Y=y;

	Vektor v;
	if(this->m_jitter!=1) {
		X+=(((float)(rand()%100))/100)-0.5f;
		Y+=(((float)(rand()%100))/100)-0.5f;
	}
	float h=this->m_height;
	float w=this->m_width;
	float r=w/h;
	v.setZ(-1.2f);
	v.setY(0.5-(float)Y*1.0f/h);
	v.setX((float)X*r/w-r/2.0f);
	return v;
}

inline int Szene::FARBE2INT(FARBE f) const {
	return (((int)(f.r*255))<<16)+(((int)(f.g*255))<<8)+(((int)(f.b*255))<<0);/**/
}

Vektor Szene::CalcDir(const Vektor &dir,const Vektor &n,STRAHL s) const {
	Vektor ret=dir;
	Vektor N=n;

	ret.Normalize();
	N.Normalize();
	if(ret.ScalarProduct(N)<0)
		N=Vektor(0,0,0)-N;

	switch(s) {
	case specular:
//		ret=dir*n.LengthQuad()-n*2*dir.ScalarProduct(n);
		ret=dir-N*2*dir.ScalarProduct(N);
		break;
	case diffus:
		break;
	}
	return ret;
}
